package com.healthybear.demo.languagechange

import android.content.Context
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AlertDialog

/**
 * ErrorHandler provides centralized error handling and user feedback for language switching operations
 * 
 * Requirements addressed:
 * - 8.4: Handle API compatibility edge cases
 * - 9.3: Gracefully fallback to alternative methods when API-specific features are unavailable
 * - 9.4: Handle API compatibility edge cases with proper error logging and user feedback
 */
object ErrorHandler {
    
    private const val TAG = "ErrorHandler"
    
    /**
     * Error types for language switching operations
     */
    enum class ErrorType {
        UNSUPPORTED_LANGUAGE,
        API_COMPATIBILITY,
        STORAGE_ERROR,
        SYSTEM_SETTINGS_ERROR,
        NETWORK_ERROR,
        UNKNOWN_ERROR
    }
    
    /**
     * Handle language switching errors with appropriate user feedback
     * Requirement 8.4, 9.3, 9.4: Error handling with fallback mechanisms
     */
    fun handleLanguageSwitchError(
        context: Context,
        error: Throwable,
        errorType: ErrorType = ErrorType.UNKNOWN_ERROR,
        showUserFeedback: Boolean = true
    ): String {
        val errorMessage = when (errorType) {
            ErrorType.UNSUPPORTED_LANGUAGE -> {
                Log.w(TAG, "Unsupported language selected", error)
                context.getString(R.string.error_unsupported_language)
            }
            ErrorType.API_COMPATIBILITY -> {
                Log.w(TAG, "API compatibility issue", error)
                context.getString(R.string.error_language_change)
            }
            ErrorType.STORAGE_ERROR -> {
                Log.e(TAG, "Storage operation failed", error)
                context.getString(R.string.error_storage_failed)
            }
            ErrorType.SYSTEM_SETTINGS_ERROR -> {
                Log.e(TAG, "System settings access failed", error)
                context.getString(R.string.error_system_settings)
            }
            ErrorType.NETWORK_ERROR -> {
                Log.w(TAG, "Network operation failed", error)
                context.getString(R.string.error_language_change)
            }
            ErrorType.UNKNOWN_ERROR -> {
                Log.e(TAG, "Unknown error occurred", error)
                context.getString(R.string.error_language_change)
            }
        }
        
        if (showUserFeedback) {
            showErrorToUser(context, errorMessage, errorType)
        }
        
        return errorMessage
    }
    
    /**
     * Handle storage errors with fallback mechanisms
     * Requirement 8.4: Handle storage failures with in-memory fallback
     */
    fun handleStorageError(context: Context, error: Throwable): String {
        Log.e(TAG, "Storage error occurred", error)
        
        // For storage errors, we can fallback to default language
        val fallbackLanguage = LanguageUtils.SupportedLanguage.ENGLISH.code
        Log.i(TAG, "Falling back to default language: $fallbackLanguage")
        
        return fallbackLanguage
    }
    
    /**
     * Handle API compatibility errors with appropriate fallback
     * Requirement 9.3, 9.4: Handle API compatibility edge cases
     */
    fun handleApiCompatibilityError(
        context: Context,
        requestedApiLevel: Int,
        currentApiLevel: Int = android.os.Build.VERSION.SDK_INT
    ): LanguageUtils.ImplementationType {
        Log.w(TAG, "API compatibility issue: requested API $requestedApiLevel, current API $currentApiLevel")
        
        // Determine the best fallback implementation type
        val fallbackType = when {
            currentApiLevel >= android.os.Build.VERSION_CODES.TIRAMISU -> {
                LanguageUtils.ImplementationType.APP_COMPAT_DELEGATE
            }
            currentApiLevel >= android.os.Build.VERSION_CODES.LOLLIPOP -> {
                LanguageUtils.ImplementationType.CONFIGURATION_UPDATE
            }
            else -> {
                LanguageUtils.ImplementationType.SYSTEM_SETTINGS
            }
        }
        
        Log.i(TAG, "Using fallback implementation type: $fallbackType")
        return fallbackType
    }
    
    /**
     * Show error message to user with appropriate UI feedback
     */
    private fun showErrorToUser(context: Context, message: String, errorType: ErrorType) {
        try {
            when (errorType) {
                ErrorType.UNSUPPORTED_LANGUAGE,
                ErrorType.STORAGE_ERROR -> {
                    // For less critical errors, show toast
                    Toast.makeText(context, message, Toast.LENGTH_LONG).show()
                }
                ErrorType.API_COMPATIBILITY,
                ErrorType.SYSTEM_SETTINGS_ERROR,
                ErrorType.NETWORK_ERROR,
                ErrorType.UNKNOWN_ERROR -> {
                    // For more critical errors, show dialog
                    showErrorDialog(context, message, errorType)
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Failed to show error to user", e)
            // Fallback to toast if dialog fails
            try {
                Toast.makeText(context, message, Toast.LENGTH_LONG).show()
            } catch (toastError: Exception) {
                Log.e(TAG, "Failed to show toast as fallback", toastError)
            }
        }
    }
    
    /**
     * Show error dialog with retry option for recoverable errors
     */
    private fun showErrorDialog(context: Context, message: String, errorType: ErrorType) {
        try {
            val builder = AlertDialog.Builder(context)
                .setTitle(context.getString(R.string.dialog_title_error))
                .setMessage(message)
                .setPositiveButton(context.getString(R.string.dialog_button_ok)) { dialog, _ ->
                    dialog.dismiss()
                }
            
            // Add retry button for recoverable errors
            if (isRecoverableError(errorType)) {
                builder.setNegativeButton(context.getString(R.string.dialog_button_retry)) { dialog, _ ->
                    dialog.dismiss()
                    // Note: Retry logic would be handled by the calling component
                }
            }
            
            val dialog = builder.create()
            dialog.show()
            
        } catch (e: Exception) {
            Log.e(TAG, "Failed to show error dialog", e)
        }
    }
    
    /**
     * Determine if an error type is recoverable (user can retry)
     */
    private fun isRecoverableError(errorType: ErrorType): Boolean {
        return when (errorType) {
            ErrorType.NETWORK_ERROR,
            ErrorType.SYSTEM_SETTINGS_ERROR -> true
            ErrorType.UNSUPPORTED_LANGUAGE,
            ErrorType.API_COMPATIBILITY,
            ErrorType.STORAGE_ERROR,
            ErrorType.UNKNOWN_ERROR -> false
        }
    }
    
    /**
     * Log error with context information for debugging
     */
    fun logErrorWithContext(
        tag: String,
        message: String,
        error: Throwable? = null,
        context: Map<String, Any> = emptyMap()
    ) {
        val contextInfo = if (context.isNotEmpty()) {
            context.entries.joinToString(", ") { "${it.key}=${it.value}" }
        } else {
            "no additional context"
        }
        
        val fullMessage = "$message (Context: $contextInfo)"
        
        if (error != null) {
            Log.e(tag, fullMessage, error)
        } else {
            Log.w(tag, fullMessage)
        }
    }
    
    /**
     * Validate language code and provide appropriate error handling
     * Requirement 8.4: Implement fallback mechanisms for unsupported languages
     */
    fun validateLanguageCode(languageCode: String): ValidationResult {
        return try {
            when {
                languageCode.isBlank() -> {
                    ValidationResult.Invalid("Language code cannot be empty")
                }
                !LanguageUtils.isLanguageSupported(languageCode) -> {
                    ValidationResult.Invalid("Unsupported language code: $languageCode")
                }
                else -> {
                    ValidationResult.Valid
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Error validating language code: $languageCode", e)
            ValidationResult.Invalid("Validation error: ${e.message}")
        }
    }
    
    /**
     * Result of language code validation
     */
    sealed class ValidationResult {
        object Valid : ValidationResult()
        data class Invalid(val reason: String) : ValidationResult()
    }
}